JS 函数缓存和使用场景
JS 函数缓存
shell
# 什么是函数缓存
函数的本质是将函数的计算结果临时缓存起来,当后续以相同参数调用该函数时,直接返回缓存的结果,而非重新执行函数逻辑。
# 实现函数缓存
函数缓存的核心是缓存参数与结果的映射,通过「空间换时间」减少重复计算 / 请求,提升性能;实现函数缓存
实现函数缓存主要依靠闭包、柯里化、高阶函数
js
/**
* 1. 利用函数闭包特性,定义缓存容器
* 2. 将函数参数拼接成唯一的键
* 3. 函数调用时,检查缓存中是否存在该键,存在则直接返回结果,不存在则执行函数,将结果存入缓存容器后返回。
* 优化:可使用 Map 结构作为缓存容器
*/
// 缓存函数封装
function createCachedFunction(fn) {
// 缓存容器(用对象存储键值对)
const cache = {};
// 返回包装后的函数
return function (...args) {
// 生成唯一的缓存键(参数拼接,简单场景可用)
const cacheKey = JSON.stringify(args);
// 检查缓存:存在则直接返回
if (cacheKey in cache) {
console.log(`命中缓存:参数 ${cacheKey}`);
return cache[cacheKey];
}
// 未命中则执行原函数,并存入缓存
console.log(`未命中缓存:参数 ${cacheKey}`);
const result = fn.apply(this, args);
cache[cacheKey] = result;
return result;
};
}
// 测试用例:模拟耗时计算函数
function calculateSum(a, b) {
// 模拟耗时操作(比如复杂计算)
console.log('执行了耗时计算');
return a + b;
}
// 创建带缓存的函数
const cachedCalculate = createCachedFunction(calculateSum);
// 第一次调用:未命中,执行计算
console.log(cachedCalculate(1, 2)); // 输出:执行了耗时计算 → 3
// 第二次调用:命中缓存,直接返回
console.log(cachedCalculate(1, 2)); // 输出:命中缓存 → 3
// 不同参数:未命中
console.log(cachedCalculate(3, 4)); // 输出:执行了耗时计算 → 7函数缓存使用场景
shell
1. 计算密集型函数:函数包含大量循环、数学计算、递归(如斐波那契数列、排序算法),且参数重复调用概率高。
2. 网络请求 / 异步数据获取:前端请求后端接口(如列表数据、详情数据),相同参数的请求无需重复发送(减少网络开销和服务器压力)。
3. 配置 / 静态数据读取:函数读取固定配置(如根据环境 / 用户角色返回不同配置),配置不会频繁变更,缓存可减少 IO / 解析开销。拓展
shell
# 函数缓存限制
如果函数依赖外部变量(如全局变量、时间)或有副作用(如修改 DOM),则不适合缓存;
# 优化
长期运行的程序需注意缓存清理,避免缓存无限增长占用内存。函数缓存(另一稿)
函数缓存是一种优化技术,通过存储函数计算结果来避免重复计算,从而提高性能(目的是优化:利用空间换时间)
如何实现函数缓存
函数闭包、函数柯里化、高阶函数
函数闭包实现缓存
对象结构存储缓存,Map 结构结构存储缓存
ts
// 对象结构存储缓存
function memoize(fn) {
const cache = {};
console.log('cache',cache)
return function(...args) {
const key = JSON.stringify(args);
if (key in cache) {
return cache[key];
}
const result = fn.apply(this, args);
cache[key] = result;
console.log('cache',cache)
return result;
};
}
// Map 结构结构存储缓存
// function memoize(fn) {
// const cache = new Map();
// return function(...args) {
// const key = JSON.stringify(args);
// if (cache.has(key)) {
// return cache.get(key);
// }
// const result = fn.apply(this, args);
// cache.set(key, result);
// return result;
// };
// }
// 使用示例
function expensiveCalculation(n) {
console.log('Calculating...');
return n * 2;
}
const memoizedCalc = memoize(expensiveCalculation);
console.log(memoizedCalc(5)); // 计算并缓存
console.log(memoizedCalc(5)); // 从缓存读取
console.log(memoizedCalc(6)); // 计算并缓存
console.log(memoizedCalc(6)); // 从缓存读取- 带过期时间的缓存
ts
function memoizeWithExpiry(fn, expiryTime) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
const now = Date.now();
if (cache[key] && now < cache[key].expiry) {
return cache[key].value;
}
const result = fn.apply(this, args);
cache[key] = {
value: result,
expiry: now + expiryTime
};
return result;
};
}
// 使用示例
function expensiveCalculation(n) {
console.log('Calculating...');
return n + 2;
}
const memoizedCalc = memoizeWithExpiry(expensiveCalculation,5000); // 缓存 5000 ms
console.log(memoizedCalc(5)); // 计算并缓存
console.log(memoizedCalc(5)); // 从缓存读取
console.log(memoizedCalc(6)); // 计算并缓存
console.log(memoizedCalc(6)); // 从缓存读取